import 'dart:io';
import 'dart:math';

import 'package:flutter_clx_base/flutter_clx_base.dart';

/// 底部导航弹框
class BottomNavigationDialog extends StatelessWidget {
  final double? latitude;
  final double? longitude;
  final String? address;

  const BottomNavigationDialog(
      {super.key, this.latitude, this.longitude, this.address});

  @override
  Widget build(BuildContext context) {
    return Container(
      decoration: const BoxDecoration(
        color: Colors.white,
        borderRadius: BorderRadius.only(
          topLeft: Radius.circular(10.0),
          topRight: Radius.circular(10.0),
        ),
      ),
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: NavigationMapTypeEnum.getOptions()
                .mapIndexed((e, i) => _rowItem(i, e.desc, () => _onMap(e)))
                ?.toList() ??
            [],
      ),
    );
  }

  /// item
  Widget _rowItem(int index, String title, VoidCallback onTap) {
    return InkWell(
      onTap: () {
        Get.back();
        onTap.call();
      },
      child: SizedBox(
        width: double.infinity,
        child: Column(
          children: [
            Offstage(offstage: index == 0, child: line()),
            vGap15,
            Text(title),
            vGap15,
          ],
        ),
      ),
    );
  }

  /// 跳转map
  void _onMap(NavigationMapTypeEnum type) {
    if (latitude == null || longitude == null) {
      ToastUtil.showToast("目的地经纬度错误");
      return;
    }
    switch (type) {
      case NavigationMapTypeEnum.apple:
        _openAppleMap(latitude!, longitude!, address: address);
        break;
      case NavigationMapTypeEnum.aMap:
        _openAMap(latitude!, longitude!, address: address);
        break;
      case NavigationMapTypeEnum.baiDu:
        _openBaiduMap(latitude!, longitude!, address: address);
        break;
      case NavigationMapTypeEnum.tencent:
        _openTencentMap(latitude!, longitude!, address: address);
        break;
      default:
    }
  }

  /// 跳转到苹果地图（iOS only）
  Future<void> _openAppleMap(double latitude, double longitude,
      {String? address}) async {
    final latLng = CoordinateConverter.gcj02ToWgs84(latitude, longitude);
    final url =
        'https://maps.apple.com/?daddr=${latLng.latitude},${latLng.longitude}&name=${Uri.encodeComponent(address ?? '目的地')}';
    final uri = Uri.parse(url);
    if (await canLaunchUrl(uri)) {
      await launchUrl(uri);
    } else {
      throw '无法打开苹果地图';
    }
  }

  /// 跳转到高德地图
  Future<void> _openAMap(double latitude, double longitude,
      {String? address}) async {
    final device = Platform.isIOS ? "iosamap://path" : "amapuri://route/plan/";
    final url =
        '$device?dlat=$latitude&dlon=$longitude&dname=${Uri.encodeComponent(address ?? '目的地')}&dev=0&t=0';
    await _toMap(url, "高德地图");
  }

  // 跳转到百度地图
  Future<void> _openBaiduMap(double latitude, double longitude,
      {String? address}) async {
    final latLng = CoordinateConverter.gcj02ToBd09(latitude, longitude);
    final url =
        'baidumap://map/direction?destination=${latLng.latitude},${latLng.longitude}&name=${Uri.encodeComponent(address ?? '目的地')}';
    await _toMap(url, "百度地图");
  }

  // 跳转到腾讯地图
  Future<void> _openTencentMap(double latitude, double longitude,
      {String? address}) async {
    final url =
        'qqmap://map/routeplan?type=drive&to=${Uri.encodeComponent(address ?? '目的地')}&tocoord=$latitude,$longitude';
    await _toMap(url, "腾讯地图");
  }

  /// 跳转地图
  Future<void> _toMap(String url, String mapName) async {
    final uri = Uri.parse(url);
    if (await _isAppInstalled(uri)) {
      await launchUrl(uri);
    } else {
      ToastUtil.showToast("请先安装$mapName");
    }
  }

  /// 是否安装应用
  Future<bool> _isAppInstalled(Uri uri) async {
    try {
      return await launchUrl(uri);
    } catch (e) {
      return false;
    }
  }
}

/// 导航地图类型
enum NavigationMapTypeEnum {
  apple(1, "Apple地图"),
  aMap(2, "高德地图"),
  baiDu(3, "百度地图"),
  tencent(4, "腾讯地图");

  const NavigationMapTypeEnum(this.value, this.desc);

  final int value;
  final String desc;

  /// 获取账户筛选
  static List<NavigationMapTypeEnum> getOptions() {
    List<NavigationMapTypeEnum> list = [];
    for (var statusEnum in NavigationMapTypeEnum.values) {
      if (!Platform.isIOS && statusEnum == NavigationMapTypeEnum.apple) {
        continue;
      }
      list.add(statusEnum);
    }
    return list;
  }
}

/// 经纬度坐标转换
class CoordinateConverter {
  static const double xPi = 3.14159265358979324 * 3000.0 / 180.0;
  static const double pi = 3.1415926535897932384626;
  static const double a = 6378245.0;
  static const double ee = 0.00669342162296594323;

  /// WGS-84 转 GCJ-02
  static LatLng wgs84ToGcj02(double lat, double lng) {
    if (_outOfChina(lat, lng)) {
      return LatLng(lat, lng);
    }
    double dLat = _transformLat(lng - 105.0, lat - 35.0);
    double dLng = _transformLng(lng - 105.0, lat - 35.0);
    double radLat = lat / 180.0 * pi;
    double magic = sin(radLat);
    magic = 1 - ee * magic * magic;
    double sqrtMagic = sqrt(magic);
    dLat = (dLat * 180.0) / (a * (1 - ee) / (magic * sqrtMagic) * pi);
    dLng = (dLng * 180.0) / (a / sqrtMagic * cos(radLat) * pi);
    double mgLat = lat + dLat;
    double mgLng = lng + dLng;
    return LatLng(mgLat, mgLng);
  }

  /// GCJ-02 转 WGS-84
  static LatLng gcj02ToWgs84(double lat, double lng) {
    LatLng gps = _transform(lat, lng);
    double lngT = lng * 2 - gps.longitude;
    double latT = lat * 2 - gps.latitude;
    return LatLng(latT, lngT);
  }

  /// GCJ-02 转 BD-09
  static LatLng gcj02ToBd09(double lat, double lng) {
    double z = sqrt(lng * lng + lat * lat) + 0.00002 * sin(lat * xPi);
    double theta = atan2(lat, lng) + 0.000003 * cos(lng * xPi);
    double bdLng = z * cos(theta) + 0.0065;
    double bdLat = z * sin(theta) + 0.006;
    return LatLng(bdLat, bdLng);
  }

  /// BD-09 转 GCJ-02
  static LatLng bd09ToGcj02(double lat, double lng) {
    double x = lng - 0.0065;
    double y = lat - 0.006;
    double z = sqrt(x * x + y * y) - 0.00002 * sin(y * xPi);
    double theta = atan2(y, x) - 0.000003 * cos(x * xPi);
    double ggLng = z * cos(theta);
    double ggLat = z * sin(theta);
    return LatLng(ggLat, ggLng);
  }

  static bool _outOfChina(double lat, double lng) {
    return !(lng > 73.66 && lng < 135.05 && lat > 3.86 && lat < 53.55);
  }

  static double _transformLat(double x, double y) {
    double ret = -100.0 +
        2.0 * x +
        3.0 * y +
        0.2 * y * y +
        0.1 * x * y +
        0.2 * sqrt(x.abs());
    ret += (20.0 * sin(6.0 * x * pi) + 20.0 * sin(2.0 * x * pi)) * 2.0 / 3.0;
    ret += (20.0 * sin(y * pi) + 40.0 * sin(y / 3.0 * pi)) * 2.0 / 3.0;
    ret += (160.0 * sin(y / 12.0 * pi) + 320 * sin(y * pi / 30.0)) * 2.0 / 3.0;
    return ret;
  }

  static double _transformLng(double x, double y) {
    double ret =
        300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * sqrt(x.abs());
    ret += (20.0 * sin(6.0 * x * pi) + 20.0 * sin(2.0 * x * pi)) * 2.0 / 3.0;
    ret += (20.0 * sin(x * pi) + 40.0 * sin(x / 3.0 * pi)) * 2.0 / 3.0;
    ret +=
        (150.0 * sin(x / 12.0 * pi) + 300.0 * sin(x / 30.0 * pi)) * 2.0 / 3.0;
    return ret;
  }

  static LatLng _transform(double lat, double lng) {
    if (_outOfChina(lat, lng)) {
      return LatLng(lat, lng);
    }
    double dLat = _transformLat(lng - 105.0, lat - 35.0);
    double dLng = _transformLng(lng - 105.0, lat - 35.0);
    double radLat = lat / 180.0 * pi;
    double magic = sin(radLat);
    magic = 1 - ee * magic * magic;
    double sqrtMagic = sqrt(magic);
    dLat = (dLat * 180.0) / (a * (1 - ee) / (magic * sqrtMagic) * pi);
    dLng = (dLng * 180.0) / (a / sqrtMagic * cos(radLat) * pi);
    double mgLat = lat + dLat;
    double mgLng = lng + dLng;
    return LatLng(mgLat, mgLng);
  }
}

class LatLng {
  final double latitude;
  final double longitude;

  LatLng(this.latitude, this.longitude);
}
